package com.bbyl.im.service;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.text.TextUtils;

import com.bbyl.IMessage;
import com.bbyl.IOnReceiveMsgCallback;
import com.bbyl.ISendMsgCallback;
import com.bbyl.im.bean.ChatMsgListRequest;
import com.bbyl.im.bean.Message;
import com.bbyl.im.bean.MsgObserverResult;
import com.bbyl.model.net.api.IApiService;
import com.bbyl.utils.Constants;
import com.github.naturs.logger.Logger;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class MsgService extends Service {

    private final RemoteCallbackList<IOnReceiveMsgCallback> receiverCallbackList = new RemoteCallbackList<>();

    public static final String TAG = "MsgService";
    public static final String CHAT_HOST = "http://job.binbinyl.com:8100/sub/";

    private Retrofit retrofit;
    private OkHttpClient client;
    private Gson gson;
    private Context context;
    private IApiService mApi = null;

    //    public static final int GRAY_SERVICE_ID = 1234;
//    private DbManager mDbManger = null;
//
    private static volatile boolean isPulling = false;
    private static volatile boolean isObserving = false;
    public static volatile MsgService mKeepAliveService = null;

    public MsgService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Logger.e("onCreate");
        context = this;
        mKeepAliveService = this;
        isObserving = false;
        isPulling = false;

        initHttpClient();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Logger.e("onDestroy");

    }

    private void initHttpClient() {
        client = new OkHttpClient.Builder()
                .connectTimeout(30, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(30, TimeUnit.SECONDS)
                .build();

        gson = new GsonBuilder()
                .setLenient()
                .registerTypeHierarchyAdapter(String.class, new JsonDeserializer<List<MsgObserverResult>>() {
                    @Override
                    public List<MsgObserverResult> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
                        if (json.isJsonArray()) {
                            //这里要自己负责解析了
                            Gson newGson = new Gson();
                            return newGson.fromJson(json, typeOfT);
                        } else {
                            Gson gson = new Gson();
                            JsonParser parser = new JsonParser();
                            String newJson = "[" + json.getAsString() + "]";
                            JsonArray Jarray = parser.parse(newJson).getAsJsonArray();

                            //方案二 构造List type

                            Type collectionType = new TypeToken<List<MsgObserverResult>>() {
                            }.getType();
//
                            return gson.fromJson(Jarray, collectionType);
                        }
                    }
                }).create();

        retrofit = new Retrofit.Builder().baseUrl(CHAT_HOST)
                .addConverterFactory(GsonConverterFactory.create())
//                .addConverterFactory(ScalarsConverterFactory.create())//首先判断是否需要转换成字符串，简单类型
                .client(client)
                .build();

        mApi = retrofit.create(IApiService.class);
    }

    /**
     * 长轮询处理 30s超时
     */
    private void pollToObserveServerMsg() {
        if (isObserving) {
            Logger.e("pollToObserveServerMsg() return ::: is observing");
            return;
        }

        isObserving = true;
        Logger.e("pollToObserveServerMsg()  ---->");

        Call<ResponseBody> call = mApi.pollAndObserve(1, "1252");
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                isObserving = false;
                if (response.body() != null && response.isSuccessful()) {
                    String result = null;
                    try {
                        result = response.body().string();
                    } catch (IOException e) {
                        e.printStackTrace();
                        Logger.e("PollingThread ---- onResponse IOException=" + e.toString());
                    }
                    Logger.e("PollingThread ---- onResponse =" + result);
                    List<MsgObserverResult> msgObserverList = convertJsonArray(result);
                    if (msgObserverList == null || msgObserverList.size() <= 0) {
                        pollToObserveServerMsg();
                        return;
                    }

                    if (TextUtils.isEmpty(msgObserverList.get(0).getContent())) {
                        pollToObserveServerMsg();
                        return;
                    }
                    //pull msg data
                    pullMessageMethod();
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Logger.e("PollingThread ----  onFailure ::: " + t.toString());
                isObserving = false;
                doRetry();
            }
        });
    }

    /**
     * 将jsonStr 解析为JsonArray 进而解析成
     *
     * @param jsonStr
     */
    private List<MsgObserverResult> convertJsonArray(String jsonStr) {
        if (TextUtils.isEmpty(jsonStr)) {
            return null;
        }
        //观察新消息返回 时间戳 list
        if (!jsonStr.contains("[{")) {
            jsonStr = "[" + jsonStr + "]";
        }
        Gson gson1 = new Gson();
        Type collectionType = new TypeToken<List<MsgObserverResult>>() {
        }.getType();
        return gson1.fromJson(jsonStr, collectionType);
    }

    /**
     * 重试整个拉消息-轮训过程
     */
    private void doRetry() {
        Logger.e("doRetry start");
        if (mTimer == null) {
            mTimer = new Timer();
            Logger.e("init mTimer");
            //30s后尝试
            if (mRetryTask == null) {
                mRetryTask = new RetryTask();
                Logger.e("init mRetryTask");
                mTimer.schedule(mRetryTask, 0, 30 * 1000);
            }
        }
    }

    private RetryTask mRetryTask;
    private static Timer mTimer;

    public class RetryTask extends TimerTask {

        private int retryCount = 0;
        private static final int MAX_TIME_RETRY = 10;

        @Override
        public void run() {
            Logger.e("RetryTask run() ::" + retryCount);

            if (isWorking()) {
                cancelRetryTask();
                return;
            }

            if (retryCount > MAX_TIME_RETRY) {
                Logger.e("RetryTask retryCount > MAX !!!");
                return;
            }

            retryCount++;
            pullMessageMethod();
        }
    }


    /**
     * 拉消息方法调用
     */
    private void pullMessageMethod() {
        Logger.e("pullMessageMethod() start");
//        if (SpHelper.DEFAULT_INT_VALUE_NON == SpHelper.INSTANCE.getLoginMode()) {
//            return;
//        }
//
//        if (isPulling) {
//            return;
//        }

        isPulling = true;

        ChatMsgListRequest msgListRequest = new ChatMsgListRequest();
        msgListRequest.setType(1);
        msgListRequest.setOs(String.valueOf(Constants.INTERFACE_OS));
        msgListRequest.setOsv(Constants.INTERFACE_VERSION);
        //获取到数据库最新消息时间
//        msgListRequest.setMsgId(getLatestMsgId());
        pullMsgData(msgListRequest);
    }

    /**
     * 拉取聊天消息
     *
     * @param msgListRequest
     */
    private void pullMsgData(ChatMsgListRequest msgListRequest) {
        Logger.e("pullMsgData() start");
        // TODO: 2018/10/26 test
        pollToObserveServerMsg();
    }

    private void cancelRetryTask() {
        if (mTimer != null) {
            mTimer.cancel();
            mTimer.purge();
            mTimer = null;
        }

        if (mRetryTask != null) {
            mRetryTask = null;
        }

    }


    /**
     * 既没有轮训，也没有拉消息，说明需要被唤起IM流程
     *
     * @return
     */
    public boolean isWorking() {
        boolean isWorking = isObserving || isPulling;
        Logger.e("is working ::" + isWorking);
        return isWorking;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Logger.e("onBind");
        //启动时，先拉取消息
        pullMessageMethod();
        return mMsgBinder;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Logger.e("onStartCommand");
        //启动时，先拉取消息
        pullMessageMethod();
        return Service.START_STICKY;
    }

    private IMessage.Stub mMsgBinder = new IMessage.Stub() {

        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

        }

        @Override
        public void registerMsgReceiver(IOnReceiveMsgCallback iOnReceiveMsgCallback) throws RemoteException {
            Logger.e("registerMsgReceiver");
            synchronized (receiverCallbackList) {
                receiverCallbackList.register(iOnReceiveMsgCallback);
            }
        }

        @Override
        public void unRegisterMsgReceiver(IOnReceiveMsgCallback iOnReceiveMsgCallback) throws RemoteException {
            Logger.e("unRegisterMsgReceiver");
            synchronized (receiverCallbackList) {
                receiverCallbackList.unregister(iOnReceiveMsgCallback);
            }
        }

        @Override
        public void sendMessage(Message msg, ISendMsgCallback callback) throws RemoteException {
            // TODO: 2018/10/26 调用发消息接口
            Logger.e("sendMessage");

        }
    };
}
